home *** CD-ROM | disk | FTP | other *** search
/ Space & Astronomy / Space and Astronomy (October 1993).iso / mac / VIEWERS / MSDOS / GIFLIB12.ZIP / UTIL / GIFROTAT.C < prev    next >
C/C++ Source or Header  |  1991-08-03  |  11KB  |  323 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Aug. 1991   *
  5. ******************************************************************************
  6. * Program to rotate a GIF image by an arbitrary angle.                 *
  7. * Options:                                     *
  8. * -q : quite printing mode.                             *
  9. * -a Angle : angle to rotate with respect to the X axis.             *
  10. * -s Width Height : specifies size of output image.                          *
  11. * -h : on line help.                                 *
  12. ******************************************************************************
  13. * History:                                     *
  14. *  2 Aug 91 - Version 1.0 by Gershon Elber.                     *
  15. *****************************************************************************/
  16.  
  17. #ifdef __MSDOS__
  18. #include <graphics.h>
  19. #include <stdlib.h>
  20. #include <alloc.h>
  21. #include <io.h>
  22. #include <dos.h>
  23. #include <bios.h>
  24. #endif /* __MSDOS__ */
  25.  
  26. #include <stdio.h>
  27. #include <math.h>
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include <fcntl.h>
  31. #include "gif_lib.h"
  32. #include "getarg.h"
  33.  
  34. #ifndef M_PI
  35. #define M_PI        3.14159265358979323846
  36. #endif /* M_PI */
  37.  
  38. #define PROGRAM_NAME    "GifRotat"
  39.  
  40. #ifdef __MSDOS__
  41. extern unsigned int
  42.     _stklen = 16384;                 /* Increase default stack size. */
  43. #endif /* __MSDOS__ */
  44.  
  45. #ifdef SYSV
  46. static char *VersionStr =
  47.     "Gif library module,\t\tGershon Elber\n\
  48.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  49. static char
  50.     *CtrlStr = "GifRotat a!-Angle!d q%- s%-Width|Height!d!d h%- GifFile!*s";
  51. #else
  52. static char
  53.     *VersionStr =
  54.     PROGRAM_NAME
  55.     GIF_LIB_VERSION
  56.     "    Gershon Elber,    "
  57.     __DATE__ ",   " __TIME__ "\n"
  58.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  59. static char
  60.     *CtrlStr =
  61.     PROGRAM_NAME
  62.     " a!-Angle!d q%- s%-Width|Height!d!d h%- GifFile!*s";
  63. #endif /* SYSV */
  64.  
  65. static int
  66.     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
  67.     InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
  68.  
  69. static void RotateGifImage(GifRowType *ScreenBuffer, GifFileType *SrcGifFile,
  70.                int Angle, GifColorType *ColorMap,
  71.                int ExpColorMapSize, int DstWidth, int DstHeight);
  72. static void RotateGifLine(GifRowType *ScreenBuffer, int BackGroundColor,
  73.               int SrcWidth, int SrcHeight,
  74.               int Angle, GifRowType DstLine,
  75.               int DstWidth, int DstHeight, int y);
  76. static void QuitGifError(GifFileType *DstGifFile);
  77.  
  78. /******************************************************************************
  79. * Interpret the command line and scan the given GIF file.              *
  80. ******************************************************************************/
  81. void main(int argc, char **argv)
  82. {
  83.     int    i, j, Size, Error, NumFiles, Col, Row, Count, ExtCode,
  84.     ExpColorMapSize, DstWidth, DstHeight, Width, Height,
  85.     ImageNum = 0,
  86.     DstSizeFlag = FALSE,
  87.     AngleFlag = FALSE,
  88.     Angle = 0,
  89.     HelpFlag = FALSE;
  90.     char **FileName = NULL;
  91.     GifRecordType RecordType;
  92.     GifByteType *Extension;
  93.     GifFileType *GifFile;
  94.     GifRowType *ScreenBuffer;
  95.     GifColorType *ColorMap = NULL;
  96.  
  97.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  98.         &AngleFlag, &Angle, &GifQuitePrint,
  99.         &DstSizeFlag, &DstWidth, &DstHeight, &HelpFlag,
  100.         &NumFiles, &FileName)) != FALSE ||
  101.         (NumFiles > 1 && !HelpFlag)) {
  102.     if (Error)
  103.         GAPrintErrMsg(Error);
  104.     else if (NumFiles > 1)
  105.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  106.     GAPrintHowTo(CtrlStr);
  107.     exit(1);
  108.     }
  109.  
  110.     if (HelpFlag) {
  111.     fprintf(stderr, VersionStr);
  112.     GAPrintHowTo(CtrlStr);
  113.     exit(0);
  114.     }
  115.  
  116.     if (NumFiles == 1) {
  117.     if ((GifFile = DGifOpenFileName(*FileName)) == NULL) {
  118.         PrintGifError();
  119.         exit(-1);
  120.     }
  121.     }
  122.     else {
  123.     /* Use the stdin instead: */
  124.  
  125. #ifdef __MSDOS__
  126.     setmode(0, O_BINARY);
  127. #endif /* __MSDOS__ */
  128.     if ((GifFile = DGifOpenFileHandle(0)) == NULL) {
  129.         PrintGifError();
  130.         exit(-1);
  131.     }
  132.     }
  133.  
  134.     /* Allocate the screen as vector of column of rows. We cannt allocate    */
  135.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  136.     /* 64k at a time and our image can be bigger than that:             */
  137.     /* Note this screen is device independent - its the screen as defined by */
  138.     /* the GIF file parameters itself.                         */
  139.     if ((ScreenBuffer = (GifRowType *)
  140.     malloc(GifFile -> SHeight * sizeof(GifRowType *))) == NULL)
  141.         GIF_EXIT("Failed to allocate memory required, aborted.");
  142.  
  143.     Size = GifFile -> SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/
  144.     if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */
  145.     GIF_EXIT("Failed to allocate memory required, aborted.");
  146.  
  147.     for (i = 0; i < GifFile -> SWidth; i++)  /* Set its color to BackGround. */
  148.     ScreenBuffer[0][i] = GifFile -> SBackGroundColor;
  149.     for (i = 1; i < GifFile -> SHeight; i++) {
  150.     /* Allocate the other rows, and set their color to background too: */
  151.     if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL)
  152.         GIF_EXIT("Failed to allocate memory required, aborted.");
  153.  
  154.     memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
  155.     }
  156.  
  157.     /* Scan the content of the GIF file and load the image(s) in: */
  158.     do {
  159.     if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
  160.         PrintGifError();
  161.         exit(-1);
  162.     }
  163.     switch (RecordType) {
  164.         case IMAGE_DESC_RECORD_TYPE:
  165.         if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
  166.             PrintGifError();
  167.             exit(-1);
  168.         }
  169.         Row = GifFile -> ITop; /* Image Position relative to Screen. */
  170.         Col = GifFile -> ILeft;
  171.         Width = GifFile -> IWidth;
  172.         Height = GifFile -> IHeight;
  173.         GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  174.             PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
  175.         if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth ||
  176.            GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) {
  177.             fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n");
  178.             exit(-2);
  179.         }
  180.         if (GifFile -> IInterlace) {
  181.             /* Need to perform 4 passes on the images: */
  182.             for (Count = i = 0; i < 4; i++)
  183.             for (j = Row + InterlacedOffset[i]; j < Row + Height;
  184.                          j += InterlacedJumps[i]) {
  185.                 GifQprintf("\b\b\b\b%-4d", Count++);
  186.                 if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
  187.                 Width) == GIF_ERROR) {
  188.                 PrintGifError();
  189.                 exit(-1);
  190.                 }
  191.             }
  192.         }
  193.         else {
  194.             for (i = 0; i < Height; i++) {
  195.             GifQprintf("\b\b\b\b%-4d", i);
  196.             if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
  197.                 Width) == GIF_ERROR) {
  198.                 PrintGifError();
  199.                 exit(-1);
  200.             }
  201.             }
  202.         }
  203.         break;
  204.         case EXTENSION_RECORD_TYPE:
  205.         /* Skip any extension blocks in file: */
  206.         if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
  207.             PrintGifError();
  208.             exit(-1);
  209.         }
  210.         while (Extension != NULL) {
  211.             if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
  212.             PrintGifError();
  213.             exit(-1);
  214.             }
  215.         }
  216.         break;
  217.         case TERMINATE_RECORD_TYPE:
  218.         break;
  219.         default:            /* Should be traps by DGifGetRecordType. */
  220.         break;
  221.     }
  222.     }
  223.     while (RecordType != TERMINATE_RECORD_TYPE);
  224.  
  225.     ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap :
  226.                        GifFile -> SColorMap);
  227.     ExpColorMapSize = GifFile -> IColorMap ? GifFile -> IBitsPerPixel :
  228.                          GifFile -> SBitsPerPixel;
  229.  
  230.     if (!DstSizeFlag) {
  231.     DstWidth = GifFile -> SWidth;
  232.     DstHeight = GifFile -> SHeight;
  233.     }
  234.  
  235.     /* Perform the actual rotation and dump the image: */
  236.     RotateGifImage(ScreenBuffer, GifFile, Angle, ColorMap, ExpColorMapSize,
  237.            DstWidth, DstHeight);
  238. }
  239.  
  240. /******************************************************************************
  241. * Save the GIF resulting image.                              *
  242. ******************************************************************************/
  243. static void RotateGifImage(GifRowType *ScreenBuffer, GifFileType *SrcGifFile,
  244.                int Angle, GifColorType *ColorMap,
  245.                int ExpColorMapSize, int DstWidth, int DstHeight)
  246. {
  247.     int i,
  248.     LineSize = DstWidth * sizeof(GifPixelType);
  249.     GifFileType *DstGifFile;
  250.     GifRowType LineBuffer;
  251.  
  252.     if ((LineBuffer = (GifRowType) malloc(LineSize)) == NULL)
  253.     GIF_EXIT("Failed to allocate memory required, aborted.");
  254.  
  255.     /* Open stdout for the output file: */
  256.     if ((DstGifFile = EGifOpenFileHandle(1)) == NULL)
  257.     QuitGifError(DstGifFile);
  258.  
  259.     if (EGifPutScreenDesc(DstGifFile, DstWidth, DstHeight,
  260.               ExpColorMapSize, 0, ExpColorMapSize,
  261.               ColorMap) == GIF_ERROR ||
  262.     EGifPutImageDesc(DstGifFile, 0, 0, DstWidth, DstHeight,
  263.              FALSE, ExpColorMapSize, NULL) == GIF_ERROR)
  264.     QuitGifError(DstGifFile);
  265.  
  266.     for (i = 0; i < DstHeight; i++) {
  267.     RotateGifLine(ScreenBuffer, SrcGifFile -> SBackGroundColor,
  268.               SrcGifFile -> SWidth, SrcGifFile -> SHeight,
  269.               Angle, LineBuffer, DstWidth, DstHeight, i);
  270.     if (EGifPutLine(DstGifFile, LineBuffer, DstWidth) == GIF_ERROR)
  271.         QuitGifError(DstGifFile);
  272.     GifQprintf("\b\b\b\b%-4d", DstHeight - i - 1);
  273.     }
  274.  
  275.     if (EGifCloseFile(DstGifFile) == GIF_ERROR)
  276.     QuitGifError(DstGifFile);
  277. }
  278.  
  279.  
  280. /******************************************************************************
  281. * Save the GIF resulting image.                              *
  282. ******************************************************************************/
  283. static void RotateGifLine(GifRowType *ScreenBuffer, int BackGroundColor,
  284.                   int SrcWidth, int SrcHeight,
  285.               int Angle, GifRowType DstLine,
  286.               int DstWidth, int DstHeight, int y)
  287. {
  288.     int x,
  289.     TransSrcX = SrcWidth / 2,
  290.     TransSrcY = SrcHeight / 2,
  291.     TransDstX = DstWidth / 2,
  292.     TransDstY = DstHeight / 2;
  293.     double SinAngle = sin(Angle * M_PI / 180.0),
  294.        CosAngle = cos(Angle * M_PI / 180.0);
  295.  
  296.     for (x = 0; x < DstWidth; x++)
  297.     {
  298.     int xc = x - TransDstX,
  299.         yc = y - TransDstY,
  300.         SrcX = xc * CosAngle - yc * SinAngle + TransSrcX,
  301.         SrcY = xc * SinAngle + yc * CosAngle + TransSrcY;
  302.  
  303.     if (SrcX < 0 || SrcX >= SrcWidth ||
  304.         SrcY < 0 || SrcY >= SrcHeight)
  305.     {
  306.         /* Out of the source image domain - set it to background color. */
  307.         *DstLine++ = BackGroundColor;
  308.     }
  309.     else
  310.         *DstLine++ = ScreenBuffer[SrcY][SrcX];
  311.     }
  312. }
  313.  
  314. /******************************************************************************
  315. * Close output file (if open), and exit.                      *
  316. ******************************************************************************/
  317. static void QuitGifError(GifFileType *DstGifFile)
  318. {
  319.     PrintGifError();
  320.     if (DstGifFile != NULL) EGifCloseFile(DstGifFile);
  321.     exit(1);
  322. }
  323.